package com.example.demo.game;

import com.example.demo.model.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.LinkedList;
import java.util.Queue;

/**
 * @Author: 啵啵虎
 * @Date: 2024-05-06  18:35
 */

//这个类表示匹配器，通过这个类负责完成整个匹配功能
    @Component
public class Matcher {

    //创建三个匹配队列
    private Queue<User> normalQueue=new LinkedList<>();
    private Queue<User> highQueue=new LinkedList<>();
    private Queue<User> veryHighQueue=new LinkedList<>();

    @Autowired
    private OnlineUserManager onlineUserManager;

    @Autowired
    private ObjectMapper objectMapper=new ObjectMapper();

    @Autowired
    private RoomManager roomManager;

    //操作匹配队列的方法
    //把玩家放到匹配队列中
    public void add(User user){
        if (user.getScore()<2000){
            synchronized (normalQueue){
                normalQueue.offer(user);
                normalQueue.notify();
            }
            System.out.println("把玩家 "+user.getUsername()+" 加入到 normalQueue 中！");
        }else if (user.getScore()>=2000 && user.getScore()<3000){
            synchronized (highQueue){
                highQueue.offer(user);
                highQueue.notify();
            }
            System.out.println("把玩家 "+user.getUsername()+" 加入到 highQueue 中！");
        }else {
            synchronized (veryHighQueue){
                veryHighQueue.offer(user);
                veryHighQueue.notify();
            }
            System.out.println("把玩家 "+user.getUsername()+" 加入到 veryHighQueue 中！");
        }
    }

    //当玩家点击停止匹配的时候，就需要把玩家从匹配队列中删除
    public void remove(User user){
        if (user.getScore()<2000){
            synchronized (normalQueue){
                normalQueue.remove(user);
            }
            System.out.println("把玩家 "+user.getUsername()+" 移除了 normalQueue");
        }else if (user.getScore()>=2000 && user.getScore()<3000){
            synchronized (highQueue){
                highQueue.remove(user);
            }
            System.out.println("把玩家 "+user.getUsername()+" 移除了 highQueue");
        }else {
            synchronized (veryHighQueue){
                veryHighQueue.remove(user);
            }
            System.out.println("把玩家 "+user.getUsername()+" 移除了 veryHighQueue");
        }
    }

    public Matcher(){
        //创建三个线程，分别针对这三个匹配队列，进行操作
        Thread t1=new Thread(){
            @Override
            public void run() {
                //扫描normalQueue
                while (true){
                    handlerMatch(normalQueue);
                }
            }
        };
        t1.start();
        Thread t2=new Thread(){
            @Override
            public void run() {
                //扫描normalQueue
                while (true){
                    handlerMatch(highQueue);
                }
            }
        };
        t2.start();
        Thread t3=new Thread(){
            @Override
            public void run() {
                //扫描normalQueue
                while (true){
                    handlerMatch(veryHighQueue);
                }
            }
        };
        t3.start();
    }

    private void handlerMatch(Queue<User> matchQueue) {
        synchronized (matchQueue){
            try {
                //1、检测队列中元素个数是否达到2
                //队列的初始情况可能是空
                //如果往队列中添加一个元素，这个时候，仍然是不能进行后续匹配操作
                //因此在这里使用while循环检查是否合理
                while (matchQueue.size()<2){
                    matchQueue.wait();
                }

                //2、尝试从队列中取出两个玩家
                User player1=matchQueue.poll();
                User player2=matchQueue.poll();
                System.out.println("匹配出两个玩家："+player1.getUsername()+","+player2.getUsername());

                //3、获取到玩家的websocket的会话
                //获取到会话的目的是为了告诉玩家，你排到了~
                WebSocketSession session1= onlineUserManager.getFromGameHall(player1.getUserId());
                WebSocketSession session2= onlineUserManager.getFromGameHall(player2.getUserId());
                //双重判定
                if (session1==null){
                    //如果玩家1现在不在线了，就把玩家2重新放回到匹配队列中
                    matchQueue.offer(player2);
                    return;
                }
                if (session2==null){
                    //如果玩家2现在不在线了，就把玩家1重新放回到匹配队列中
                    matchQueue.offer(player1);
                    return;
                }
                //当前能否排到两个玩家是同一个用户的情况吗?
                //理论不会出现
                //1、如果玩家下线，就会把玩家移出匹配队列
                //2、又禁止了玩家多开
                if (session1==session2){
                    //把其中一个玩家放回匹配队列
                    matchQueue.offer(player1);
                    return;
                }

                //4、把这两个玩家放回到一个游戏房间
                Room room=new Room();
                roomManager.add(room, player1.getUserId(),player2.getUserId());


                //5、给玩家反馈信息：你匹配到对手了、
                //通过websocket返回一个message为‘matchSuccess’这样的响应
                //此处要给两个玩家都返回信息
                MatchResponse response1=new MatchResponse();
                response1.setOk(true);
                response1.setMessage("matchSuccess");
                String json1=objectMapper.writeValueAsString(response1);
                session1.sendMessage(new TextMessage(json1));

                MatchResponse response2=new MatchResponse();
                response2.setOk(true);
                response2.setMessage("matchSuccess");
                String json2=objectMapper.writeValueAsString(response2);
                session2.sendMessage(new TextMessage(json2));
            }catch (InterruptedException | IOException e){
                e.printStackTrace();
            }
        }
    }
}
